package test.controller;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.UUID;

import javax.imageio.ImageIO;

import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Positions;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;

import test.couchdb.ModelsDb;
import test.domain.Model3D;
import test.domain.ModelImage;
import test.form.ModelForm;

import com.n1global.acc.CouchDbDocIdAndRev;
import com.n1global.acc.json.CouchDbDocumentAttachment;
import com.ning.http.util.Base64;

@Controller
@RequestMapping("/admin/asdfgh")
public class AdminController {
    @Autowired
    private ModelsDb modelsDb;

    @RequestMapping(method = RequestMethod.GET)
    public String get(Model model) {
        model.addAttribute("models", modelsDb.getModelsView().createQuery().asValues());

        return "/admin";
    }

    @RequestMapping(value = "/editModel/new", method = RequestMethod.GET)
    public String newModel(@SuppressWarnings("unused") @ModelAttribute("modelForm") ModelForm form, Model model) {
        model.addAttribute("images", new ArrayList<>());

        return "/edit_model";
    }

    @RequestMapping(value = "/editModel/{id}", method = RequestMethod.GET)
    public String editModel(@PathVariable String id, Model model) {
        Model3D model3d = modelsDb.get(id);

        ModelForm modelForm = new ModelForm();

        BeanUtils.copyProperties(model3d, modelForm);

        model.addAttribute(modelForm);
        model.addAttribute("images", model3d.getImages());

        return "/edit_model";
    }

    @RequestMapping(value = "/saveModel", method = RequestMethod.POST)
    public String saveModel(ModelForm modelForm) throws IOException {
        Model3D model3d = (Model3D) (modelForm.getDocId().isEmpty() ? new Model3D() : modelsDb.get(modelForm.getDocId()));

        BeanUtils.copyProperties(modelForm, model3d);

        modelsDb.saveOrUpdate(model3d);

        return "redirect:/admin/asdfgh";
    }

    @RequestMapping(value = "/deleteModel", method = RequestMethod.POST)
    public String deleteModel(String id, String rev) {
        modelsDb.delete(new CouchDbDocIdAndRev(id, rev));

        return "redirect:/admin/asdfgh";
    }

    @RequestMapping(value = "/deleteImage/{id}/{index}", method = RequestMethod.POST)
    public String deleteImage(@PathVariable String id, @PathVariable int index) {
        Model3D model3d = modelsDb.get(id);

        ModelImage image = model3d.getImages().get(index);

        model3d.deleteAttachment(image.getFullImage());
        model3d.deleteAttachment(image.getPreviewImage());

        model3d.getImages().remove(index);

        modelsDb.saveOrUpdate(model3d);

        return "redirect:/admin/asdfgh/editModel/{id}";
    }

    @RequestMapping(value = "/addImage/{id}", method = RequestMethod.POST)
    public String addImage(@PathVariable String id, MultipartFile image) throws IOException {
        Model3D model3d = modelsDb.get(id);

        String fullName = UUID.randomUUID().toString();
        String previewName = UUID.randomUUID().toString();

        try (InputStream in = image.getInputStream();
             ByteArrayOutputStream out = new ByteArrayOutputStream()) {
            BufferedImage bufImage = ImageIO.read(in);

            Thumbnails.of(bufImage).size(1200, 1200).crop(Positions.CENTER).outputQuality(0.9).outputFormat("JPEG").toOutputStream(out);
            model3d.addAttachment(fullName, new CouchDbDocumentAttachment("image/jpeg", Base64.encode(out.toByteArray())));
            out.reset();

            Thumbnails.of(bufImage).size(300, 300).crop(Positions.CENTER).outputQuality(0.9).outputFormat("JPEG").toOutputStream(out);
            model3d.addAttachment(previewName, new CouchDbDocumentAttachment("image/jpeg", Base64.encode(out.toByteArray())));
        }

        model3d.getImages().add(new ModelImage(fullName, previewName));

        modelsDb.saveOrUpdate(model3d);

        return "redirect:/admin/asdfgh/editModel/{id}";
    }
}
